/**
 * <strong>工厂方法是一种创建型设计模式，解决了在不指定具体类的情况下创建产品对象的问题。<br>
 * 工厂方法定义了一个方法，且必须使用该方法代替通过直接调用构造函数来创建对象（<code>new</code>操作符）的方式。子类可重写该方法来更改将被创建的对象所属类。<br>
 * 在 Java 中使用模式</strong><br>
 * <br>
 * 使用示例：工厂方法模式在 Java 代码中得到了广泛使用。当你需要在代码中提供高层次的灵活性时，该模式会非常实用。<br>
 * 核心 Java 程序库中有该模式的应用：<br>
 * {@link java.util.Calendar#getInstance()}<br>
 * {@link java.util.ResourceBundle#getBundle(java.lang.String)}<br>
 * {@link java.text.NumberFormat#getInstance()}<br>
 * {@link java.nio.charset.Charset#forName(java.lang.String)}<br>
 * {@link java.net.URLStreamHandlerFactory#createURLStreamHandler(String)}（根据协议返回不同的单例对象）<br>
 * {@link java.util.EnumSet#of(java.lang.Enum)}<br>
 * {@link javax.xml.bind.JAXBContext#createMarshaller()}及其他类似的方法。<br>
 * 识别方法：工厂方法可通过构建方法来识别，它会创建具体类的对象，但以抽象类型或接口的形式返回这些对象。<br>
 * <br>
 * <strong>生成跨平台的 GUI 元素</strong><br>
 * 在本例中，按钮担任产品的角色，对话框担任创建者的角色。<br>
 * 不同类型的对话框需要其各自类型的元素。因此我们可为每个对话框类型创建子类并重写其工厂方法。<br>
 * 现在，每种对话框类型都将对合适的按钮类进行初始化。对话框基类使用其通用接口与对象进行交互，因此代码更改后仍能正常工作。<br>
 * <br>
 * <strong>工厂方法模式适合应用场景</strong><br>
 * 场景：<br>
 * 当你在编写代码的过程中，如果无法预知对象确切类别及其依赖关系时，可使用工厂方法。<br>
 * 解决：<br>
 * 工厂方法将创建产品的代码与实际使用产品的代码分离，从而能在不影响其他代码的情况下扩展产品创建部分代码。<br>
 * 例如，如果需要向应用中添加一种新产品，你只需要开发新的创建者子类，然后重写其工厂方法即可。<br>
 * <br>
 * 场景：<br>
 * 如果你希望用户能扩展你软件库或框架的内部组件，可使用工厂方法。<br>
 * 解决：<br>
 * 继承可能是扩展软件库或框架默认行为的最简单方法。但是当你使用子类替代标准组件时，框架如何辨识出该子类？<br>
 * 解决方案是将各框架中构造组件的代码集中到单个工厂方法中，并在继承该组件之外允许任何人对该方法进行重写。<br>
 * 让我们看看具体是如何实现的。假设你使用开源 UI 框架编写自己的应用。你希望在应用中使用圆形按钮，但是原框架仅支持矩形按钮。你可以使用<code>圆形按钮Round­Button</code>子类来继承标准的<code>按钮Button</code>类。但是，你需要告诉<code>UI框架UIFramework</code>类使用新的子类按钮代替默认按钮。<br>
 * 为了实现这个功能，你可以根据基础框架类开发子类<code>圆形按钮 UIUIWith­Round­Buttons</code>，并且重写其<code>create­Button创建按钮</code>方法。基类中的该方法返回<code>按钮</code>对象，而你开发的子类返回<code>圆形按钮</code>对象。现在，你就可以使用<code>圆形按钮 UI</code>类代替<code>UI框架</code>类。 就是这么简单！<br>
 * <br>
 * 场景：<br>
 * 如果你希望复用现有对象来节省系统资源，而不是每次都重新创建对象，可使用工厂方法。
 * 解决：<br>
 * 在处理大型资源密集型对象（比如数据库连接、文件系统和网络资源）时，你会经常碰到这种资源需求。<br>
 * 让我们思考复用现有对象的方法：
 * <ol>
 *     <li>首先，你需要创建存储空间来存放所有已经创建的对象。</li>
 *     <li>当他人请求一个对象时，程序将在对象池中搜索可用对象。</li>
 *     <li>…然后将其返回给客户端代码。</li>
 *     <li>如果没有可用对象，程序则创建一个新对象（并将其添加到对象池中）。</li>
 * </ol>
 * 这些代码可不少！而且它们必须位于同一处，这样才能确保重复代码不会污染程序。<br>
 * 可能最显而易见，也是最方便的方式，就是将这些代码放置在我们试图重用的对象类的构造函数中。但是从定义上来讲，构造函数始终返回的是新对象，其无法返回现有实例。<br>
 * 因此，你需要有一个既能够创建新对象，又可以重用现有对象的普通方法。这听上去和工厂方法非常相像。<br>
 * <br>
 * <strong>实现方式</strong>
 * <ol>
 *     <li>让所有产品都遵循同一接口。该接口必须声明对所有产品都有意义的方法。</li>
 *     <li>在创建类中添加一个空的工厂方法。该方法的返回类型必须遵循通用的产品接口。</li>
 *     <li>在创建者代码中找到对于产品构造函数的所有引用。将它们依次替换为对于工厂方法的调用，同时将创建产品的代码移入工厂方法。<br>
 *     你可能需要在工厂方法中添加临时参数来控制返回的产品类型。<br>
 *     工厂方法的代码看上去可能非常糟糕。其中可能会有复杂的 switch分支运算符，用于选择各种需要实例化的产品类。但是不要担心，我们很快就会修复这个问题。</li>
 *     <li>现在，为工厂方法中的每种产品编写一个创建者子类，然后在子类中重写工厂方法，并将基本方法中的相关创建代码移动到工厂方法中。</li>
 *     <li>如果应用中的产品类型太多，那么为每个产品创建子类并无太大必要，这时你也可以在子类中复用基类中的控制参数。</li>
 *     <li>如果代码经过上述移动后，基础工厂方法中已经没有任何代码，你可以将其转变为抽象类。如果基础工厂方法中还有其他语句，你可以将其设置为该方法的默认行为。</li>
 * </ol>
 * <br>
 * <strong>工厂方法模式优缺点</strong>
 * 优点：
 * <ol>
 *     <li>你可以避免创建者和具体产品之间的紧密耦合。</li>
 *     <li>单一职责原则。你可以将产品创建代码放在程序的单一位置，从而使得代码更容易维护。</li>
 *     <li>开闭原则。无需更改现有客户端代码，你就可以在程序中引入新的产品类型。</li>
 * </ol>
 * 缺点：
 * <ol>
 *     <li>应用工厂方法模式需要引入许多新的子类，代码可能会因此变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。</li>
 * </ol>
 * <strong>与其他模式的关系</strong>
 * <ul>
 *     <li>在许多设计工作的初期都会使用工厂方法模式（较为简单，而且可以更方便地通过子类进行定制），随后演化为使用抽象工厂模式、原型模式或生成器模式（更灵活但更加复杂）。</li>
 *     <li>抽象工厂模式通常基于一组工厂方法，但你也可以使用原型模式来生成这些类的方法。</li>
 *     <li>你可以同时使用工厂方法和迭代器模式来让子类集合返回不同类型的迭代器，并使得迭代器与集合相匹配。</li>
 *     <li>原型并不基于继承，因此没有继承的缺点。另一方面，原型需要对被复制对象进行复杂的初始化。工厂方法基于继承，但是它不需要初始化步骤。</li>
 *     <li>工厂方法是模板方法模式的一种特殊形式。同时，工厂方法可以作为一个大型模板方法中的一个步骤。</li>
 * </ul>
 */
package com.cg.design.depthdesign.factorymethod;